package com.finger.gulimall.cart.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.finger.common.constant.CartConstant;
import com.finger.common.to.cart.CartItemTo;
import com.finger.common.utils.R;
import com.finger.gulimall.cart.feign.ProductRemoteService;
import com.finger.gulimall.cart.interceptor.CartCookieInterceptor;
import com.finger.gulimall.cart.service.CartService;
import com.finger.gulimall.cart.to.UserInfoTo;
import com.finger.gulimall.cart.vo.Cart;
import com.finger.gulimall.cart.vo.CartItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private ProductRemoteService productRemoteService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ThreadPoolExecutor executor;

    @Override
    public CartItem addToCart(Long skuId, Integer num) throws ExecutionException, InterruptedException {

        BoundHashOperations<String, Object, Object> cartOps = getCart();

        String item = (String) cartOps.get(skuId.toString());
        if (StringUtils.isEmpty(item)) {
            // 该购物车中没有该商品
            CartItem cartItem = new CartItem();
            CompletableFuture<Void> cartDataFuture = CompletableFuture.runAsync(() -> {
                // 从远程服务器获取该商品信息
                R resData = productRemoteService.cartInfo(skuId);
                if (resData.getCode() == 0) {
                    CartItemTo data = resData.getData(new TypeReference<CartItemTo>(){});
                    cartItem.setImage(data.getSkuDefaultImg());
                    cartItem.setCount(num);
                    cartItem.setPrice(data.getPrice());
                    cartItem.setTitle(data.getSkuTitle());
                    cartItem.setCheck(true);
                    cartItem.setSkuId(skuId);
                }
            }, executor);

            CompletableFuture<Void> attrAttrFuture = CompletableFuture.runAsync(() -> {
                // 从远程服务获取该商品的销售属性
                R resAttr = productRemoteService.getAttrForCartItem(skuId);
                if (resAttr.getCode() == 0) {
                    ArrayList<String> attr = resAttr.getData(new TypeReference<ArrayList>(){});
                    cartItem.setSkuAttr(attr);
                }
            }, executor);
            // 阻塞，等以上两个线程完成之后继续执行
            CompletableFuture.allOf(cartDataFuture, attrAttrFuture).get();
            // 将该商品存入该购物车
            cartOps.put(skuId.toString(), JSON.toJSONString(cartItem));
            return cartItem;
        } else {
            // 该购物车中有该商品，只需要更改数量即可
            CartItem cartItem = JSON.parseObject(item, new TypeReference<CartItem>() {
            });
            cartItem.setCount(cartItem.getCount() + num);
            String jsonString = JSON.toJSONString(cartItem);
            cartOps.put(skuId.toString(), jsonString);
            return cartItem;
        }
    }

    @Override
    public CartItem getItem(Long skuId) {

        BoundHashOperations<String, Object, Object> cartOps = getCart();
        // 根据skuid找到在该购物车中的数据
        String res = (String) cartOps.get(skuId.toString());
        if (!StringUtils.isEmpty(res)) {
            // 如果存在解析成前端需要的格式，返回
            CartItem cartItem = JSON.parseObject(res, CartItem.class);
            return cartItem;
        }
        return null;
    }


    public BoundHashOperations<String, Object, Object> getCart() {
        UserInfoTo infoTo = CartCookieInterceptor.threadLocal.get();
        Long userId = infoTo.getUserId();

        if (userId != null) {
            // 用户已经登录
            BoundHashOperations<String, Object, Object> hashOps = redisTemplate.boundHashOps(CartConstant.CART_PREFIX + userId.toString());
            return hashOps;
        } else {
            String userKey = infoTo.getUserKey();
            // 未登录临时用户
            BoundHashOperations<String, Object, Object> hashOps = redisTemplate.boundHashOps(CartConstant.CART_PREFIX + userKey);
            return hashOps;
        }
    }

    @Override
    public Cart getCartWithItems() {

        UserInfoTo infoTo = CartCookieInterceptor.threadLocal.get();
        Long userId = infoTo.getUserId();
        BoundHashOperations<String, Object, Object> hashOps = null;
        if (userId != null) {
            // 用户登录状态，使用用户购物车
            Cart cart = new Cart();
            hashOps = redisTemplate.boundHashOps(CartConstant.CART_PREFIX + userId.toString());
            List<CartItem> cartItems = new ArrayList<>();
            List<Object> userCartItems = hashOps.values();
            if (userCartItems != null && userCartItems.size() > 0) {
                List<CartItem> items = userCartItems.stream().map(item -> {
                    String s = (String) item;
                    CartItem cartItem = JSON.parseObject(s, CartItem.class);
                    return cartItem;
                }).collect(Collectors.toList());
                cartItems = items;
            }
            // TODO 购物车合并需要改良
            String userKey = infoTo.getUserKey();
            if (!StringUtils.isEmpty(userKey)) {
                // 合并用户登录后的购物车数据，和用户使用临时购物车添加的数据
                BoundHashOperations<String, Object, Object> tempOps = redisTemplate.boundHashOps(CartConstant.CART_PREFIX + userKey);
                List<Object> values = tempOps.values();
                if (cartItems.size() > 0) {
                    if(values!=null && values.size()>0){
                        // 如果用户登录后的购物车有数据，判断两个购物车中是否有商品重复，如果有商品重复，添加数量
                        Map<String, CartItem> collect = cartItems.stream().collect(Collectors.toMap(item -> {
                            return item.getSkuId().toString();
                        }, item -> {
                            return item;
                        }));
                        for (Object value : values) {
                            String s = (String) value;
                            CartItem cartItem = JSON.parseObject(s, CartItem.class);
                            CartItem item = collect.get(cartItem.getSkuId().toString());
                            if (item != null) {
                                // 如果item不为空，说明用户购物车里边存在该商品，将购物车中的商品添加数量
                                item.setCount(cartItem.getCount()+item.getCount());
                            } else {
                                // 如果item为空，说明用户登录后的购物车里不存在临时购物车中的商品
                                cartItems.add(cartItem);
                            }
                        }
                    }
                } else {

                    if (values != null && values.size() > 0) {
                        // 如果用户登录后的购物车没有数据，直接把临时购物车里的内容放到用户登录后的购物车里，并删除临时购物车
                        List<CartItem> tempCartItems = values.stream().map(item -> {
                            String s = (String) item;
                            CartItem cartItem = JSON.parseObject(s, CartItem.class);
                            return cartItem;
                        }).collect(Collectors.toList());
                        cartItems.addAll(tempCartItems);
                    }
                }

                redisTemplate.delete(CartConstant.CART_PREFIX + userKey);
            }

            cart.setItems(cartItems);
            if (cartItems.size() > 0) {
                Map<String, String> itemMap = cartItems.stream().collect(Collectors.toMap(item -> {
                    return item.getSkuId().toString();
                }, item -> {
                    return JSON.toJSONString(item);
                }));
                hashOps.putAll(itemMap);
            }

            return cart;

        } else {
            // 用户未登录，使用临时购物车
            Cart cart = new Cart();
            String userKey = infoTo.getUserKey();
            hashOps = redisTemplate.boundHashOps(CartConstant.CART_PREFIX + userKey);
            List<Object> values = hashOps.values();
            List<CartItem> cartItems = values.stream().map(item -> {
                String s = (String) item;
                CartItem cartItem = JSON.parseObject(s, CartItem.class);
                return cartItem;
            }).collect(Collectors.toList());
            cart.setItems(cartItems);
            return cart;
        }
    }

    @Override
    public void updateCheckStatus(Integer check, Long skuId) {
        if (check != null && skuId != null) {
            CartItem item = getItem(skuId);
            if (item != null) {
                // 更新选中状态
                item.setCheck(check == 1);
                // 更新缓存中商品选中状态
                BoundHashOperations<String, Object, Object> cart = getCart();
                cart.put(skuId.toString(), JSON.toJSONString(item));
            }
        }
    }

    @Override
    public void updateCountNum(Long skuId, Integer num) {
        if (skuId != null && num != null && num > 0) {
            CartItem item = getItem(skuId);
            if (item != null) {
                // 更新选中状态
                item.setCount(num);
                // 更新缓存中商品选中状态
                BoundHashOperations<String, Object, Object> cart = getCart();
                cart.put(skuId.toString(), JSON.toJSONString(item));
            }
        }
    }

    @Override
    public void removeItem(Long skuId) {
        if (skuId != null) {
            BoundHashOperations<String, Object, Object> cart = getCart();
            // 讲该商品从购物车中移除
            cart.delete(skuId.toString());
        }
    }

    /**
     * 供订单模块调用，获取当前用户选中的全部订单项
     * @return
     */
    @Override
    public List<CartItem> getItemsForOrderConfirm() {

        BoundHashOperations<String, Object, Object> cart = getCart();
        // 购物车中hash存购物车，field-》value = skiId-》sku
        List<Object> values = cart.values();
        // 将购物车中选中的购物项过滤出来
        List<CartItem> cartItems = values.stream().map(item -> {
            String sku = (String) item;
            CartItem cartItem = JSON.parseObject(sku, CartItem.class);
            return cartItem;
        }).filter(item -> {
            return item.getCheck();
        }).collect(Collectors.toList());

        // 查出选中购物项的最新价格
       if(cartItems!=null && cartItems.size()>0){
           List<Long> checkdSkuIds = cartItems.stream().map(item -> item.getSkuId()).collect(Collectors.toList());
           // 从商品服务查最新价格
           R res = productRemoteService.getNewItemPriceForCart(checkdSkuIds);
           Map<Long, BigDecimal> map = res.getData(new TypeReference<Map<Long, BigDecimal>>() {
           });
           // 设置购物车中商品最新价格
           for (CartItem cartItem : cartItems) {
               Long skuId = cartItem.getSkuId();
               cartItem.setPrice(map.get(skuId));
           }
       }

       return cartItems;
    }
}
